package com.huanghuang.shuadan.common.aop.validation;

import com.huanghuang.shuadan.common.annotation.vaildation.Validation;
import com.huanghuang.shuadan.common.exception.base.BaseExceptionEnum;
import com.huanghuang.shuadan.common.exception.vaild.VaildEnum;
import com.huanghuang.shuadan.common.exception.vaild.ValidException;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author suxiaoxiao
 * @Date 2019/7/14 0:55
 * @Version 1.0
 */
public class Check {

    public static void check(Object o) {
        if (null == o) {
            return;
        }
        Class clazz = o.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        fieldList.forEach(field -> {
            field.setAccessible(true);
            try {
                // 实体类属性值
                Object value = field.get(o);
                // 该实体类属性上的注解
                Validation annotation = field.getAnnotation(Validation.class);
                if (null == annotation) {
                    return;
                }
                checkNotNull(value, annotation, field.getName());
                checkPattern(value, annotation, field.getName());
                checkMax(value, annotation, field.getName());
                checkMin(value, annotation, field.getName());
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                //数据解析失败
                throw new ValidException(BaseExceptionEnum.PARAMS_VALID_FAILED);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw new ValidException(BaseExceptionEnum.PARAMS_VALID_FAILED);
            }
        });
    }

    private static void checkNotNull(Object value, Validation validation, String fieldName) {
        if (validation.notNull() && value == null) {
            throw new ValidException(VaildEnum.PARAMETER_CANNOT_BE_EMPTY, fieldName);
        }
    }

    private static void checkPattern(Object value, Validation validation, String fieldName) {
        if (null != validation.pattern() && validation.pattern().length() > 0) {
            Pattern p = Pattern.compile(validation.pattern());
            Matcher m = p.matcher(value.toString());
            if (!m.matches()) {
                throw new ValidException(VaildEnum.PATTERN_CHECK_FAILED, fieldName);
            }
        }
    }

    private static void checkMax(Object value, Validation validation, String fieldName) {
        if (("").equals(validation.max())) {
            return;
        }
        if (string2double(validation.max()) > 0) {
            if (value instanceof String) {
                if (value.toString().length() > string2double(validation.max())) {
                    throw new ValidException(VaildEnum.MAX_VALID_FAILED, fieldName);
                }
            } else {
                if (objectToDouble(value) > string2double(validation.max())) {
                    throw new ValidException(VaildEnum.MAX_VALID_FAILED, fieldName);
                }
            }
        }
    }

    private static void checkMin(Object value, Validation validation, String fieldName) {
        if (("").equals(validation.min())) {
            return;
        }
        if (string2double(validation.min()) >= 0) {
            if (value instanceof String) {
                if (value.toString().length() < string2double(validation.min())) {
                    throw new ValidException(VaildEnum.MIN_VALID_FAILED, fieldName);
                }
            } else {
                if (objectToDouble(value) < string2double(validation.min())) {
                    throw new ValidException(VaildEnum.MIN_VALID_FAILED, fieldName);
                }
            }
        }
    }

    private static double objectToDouble(Object o) {
        return Double.valueOf(o.toString());
    }

    private static double string2double(String string) {
        double d = 0;
        try {
            d = Double.valueOf(string);
        } catch (ClassCastException e) {
            e.printStackTrace();
        }
        return d;
    }

}
